package com.by.basicweb.utils;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.by.toolkit.enums.ErrorCodeEnum;
import com.by.toolkit.model.Resp;
import com.by.toolkit.utils.IpUtil;
import com.google.common.collect.Maps;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Map;
import java.util.Objects;

import static com.by.toolkit.utils.ExceptionUtil.getStackTrace;
import static com.by.toolkit.utils.ExceptionUtil.nullError;

@Slf4j
public class HttpServletUtil {

    private static final HttpServletUtil INSTANCE = new HttpServletUtil();

    private HttpServletUtil() {
    }

    public static Map<String, String> httpQueryParam() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        Map<String, String> retVal = Maps.newHashMap();
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String key = parameterNames.nextElement();
            String val = request.getParameter(key);
            retVal.put(key, val);
        }
        return retVal;
    }

    public static String userAgent() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        return request.getHeader("User-Agent");
    }

    public static String remoteIpv4() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        return IpUtil.getRemoteIpV4(request);
    }

    public static void writeResponse(ErrorCodeEnum errorCodeEnum) {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        nullError(servletRequestAttributes, "servlet request context is null");
        HttpServletResponse response = servletRequestAttributes.getResponse();
        response.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
        response.setContentType("text/json; charset=UTF-8");
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
            writer.print(JSON.toJSON(new Resp<>(errorCodeEnum)));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (Objects.nonNull(writer)) {
                writer.close();
                writer.flush();
            }
        }
    }

    public static void writeResponse(String msg) {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = servletRequestAttributes.getResponse();
        writeResponse(msg);
    }

    public static void writeResponse(HttpServletResponse response, String msg) {
        response.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
        response.setContentType("text/json; charset=UTF-8");
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
            writer.print(JSON.toJSON(Resp.bizFail(msg)));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (Objects.nonNull(writer)) {
                writer.close();
                writer.flush();
            }
        }

    }

    public static void writeOkResponse() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = servletRequestAttributes.getResponse();
        response.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
        response.setContentType("application/json; charset=UTF-8");
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
            writer.print(JSON.toJSON(Resp.ok()));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (Objects.nonNull(writer)) {
                writer.close();
                writer.flush();
            }
        }

    }

    public static void responseDownload(String fileName, byte[] fileBytes) throws IOException {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = servletRequestAttributes.getResponse();
        response.reset();
        response.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", StrUtil.format("attachment;filename={}", fileName));

        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            outputStream.write(fileBytes);
        } catch (Exception e) {
            log.error("[HttpServletUtil][responseDownload] [HasException]:[{}]", getStackTrace(e));
        } finally {
            if (Objects.nonNull(outputStream)) {
                outputStream.flush();
                outputStream.close();
            }
        }
    }

}
